#!/usr/bin/env python
"""
Convert fonts from the font-bin directory.
Reads romfont bin files from the input-file and writes
python font files according to the specified chinese string(-s).  

Example:

    #cnfont_from_bin.py input:font-bin output:pyfont -w:font_width -s:font_text
    cnfont_from_bin.py unicn_16x16.bin unicn_16x16.py -w 16  -s "你好啊"

requires argparse
"""
import os
import re
import argparse


def convert_font(file_in, file_out, width, height, str, first=0x4e00, last=0x9fa5):
    chunk_size = height * width//8
    start = first - 0x4e00
    end  = last - 0x4e00

    with open(file_out, 'wt',encoding = "UTF-8") as font_file:
        print(f'"""converted from {file_in} """', file=font_file)
        print(f'WIDTH = {width}', file=font_file)
        print(f'HEIGHT = {height}', file=font_file)
        print(f'FIRST = 0x{first:04x}', file=font_file)
        print(f'LAST = 0x{last:04x}', file=font_file)
        print(f'MAP = "{str}"', file=font_file)
        print(f'_FONT =\\\n', sep='', end='', file=font_file)
        with open(file_in, "rb") as bin_file:
            for chr in str:
                file_offset = (ord(chr) - 0x4e00) * chunk_size
                bin_file.seek(file_offset)
                chunk = bin_file.read(chunk_size)
                print('b\'', sep='', end = '', file = font_file)
                for data in chunk:
                    print(f'\\x{data:02x}', end='', file=font_file)
                print('\'\\', file=font_file)

        print('', file=font_file)
        print('FONT = memoryview(_FONT)', file=font_file)

def auto_int(x):
        return int(x, 0)

def main():

    parser = argparse.ArgumentParser(
        description='Convert fomfont.bin font files in input to python in font_directory.')
    parser.add_argument('input', help='file or directory containing binary font file(s).')
    parser.add_argument('output', help='file or directory to contain python font file(s).')
    parser.add_argument('-w', '--width', type=auto_int, default=16)
    parser.add_argument('-f', '--first-char', type=auto_int, default=0x4e00)
    parser.add_argument('-l', '--last-char', type=auto_int, default=0x9fa5)
    parser.add_argument('-s', '--text', type=str)
    args = parser.parse_args()

    file_re = re.compile(r'^(.*)(\d+)x(\d+)\.bin$')

    is_dir = os.path.isdir(args.input)
    if is_dir:
        bin_files = os.listdir(args.input)
    else:
        bin_files = [args.input]

    for bin_file_name in bin_files:
        match = file_re.match(bin_file_name)
        if match:
            font_width = args.width
            print("font_width:",font_width)
            font_height = int(match.group(3))

            if is_dir:
                bin_file_name = args.input+'/'+bin_file_name

            if is_dir:
                font_file_name = (
                    args.font_directory + '/' +
                    match.group(1).rstrip('_').lower()+
                    f'_{font_width}x{font_height}.py')
            else:
                font_file_name = args.output

            print("converting", bin_file_name, 'to', font_file_name)
            text_map = ""
            for chr in args.text:
                if chr not in text_map:
                    text_map += chr
            print("txt map:",text_map)
            convert_font(
                bin_file_name,
                font_file_name,
                font_width,
                font_height,
                text_map,
                args.first_char,
                args.last_char)
main()
